﻿using Authority.DataTransferObject.Role;
using Authority.Doamin;
using Authority.Doamin.IRepository;
using Authority.Doamin.View;
using Authority.EFRepositoryImpl;
using Authority.IServices;
using Authority.IServices.Model.Role;
using AutoMapper;
using HelperFromTheSkeleton.Convert;
using HelperFromTheSkeleton.Enums;
using HelperFromTheSkeleton.ExtendMethod;

namespace Authority.ServiceImpl
{
    /// <summary>
    /// 角色权限服务
    /// </summary>
    public class RoleAuthorityServiceImpl : IRoleAuthorityService
    {
        private readonly IUserRoleAuthorityRepository _userRoleAuthorityRepository;
        private readonly IRoleAuthorityRepository _roleAuthorityRepository;
        private readonly IRoleAuthorityMenuRepository _roleAuthorityMenuRepository;
        private readonly IRoleAuthorityActionRepository _roleAuthorityActionRepository;
        private readonly IRoleAuthorityRoutingRepository _roleAuthorityRoutingRepository;
        private readonly IActionAuthorityRepository _actionAuthorityRepository;
        private readonly IMenuAuthorityRepository _menuAuthorityRepository;
        private readonly IRoutingAuthorityRepository _routingAuthorityRepository;
        private readonly IUnitWork _unitWork;
        private readonly IMapper _mapper;

        public RoleAuthorityServiceImpl(IUnitWork unitWork,
            IRoleAuthorityMenuRepository roleAuthorityMenuRepository,
            IRoleAuthorityActionRepository roleAuthorityActionRepository,
            IRoleAuthorityRoutingRepository roleAuthorityRoutingRepository,
            IActionAuthorityRepository actionAuthorityRepository,
            IMenuAuthorityRepository menuAuthorityRepository,
            IRoutingAuthorityRepository routingAuthorityRepository,
            IUserRoleAuthorityRepository userRoleAuthorityRepository,
            IMapper mapper,
        IRoleAuthorityRepository roleAuthorityRepository
            )
        {
            _roleAuthorityRepository = roleAuthorityRepository;
            _roleAuthorityMenuRepository = roleAuthorityMenuRepository;
            _roleAuthorityActionRepository = roleAuthorityActionRepository;
            _roleAuthorityRoutingRepository = roleAuthorityRoutingRepository;
            _actionAuthorityRepository = actionAuthorityRepository;
            _menuAuthorityRepository = menuAuthorityRepository;
            _routingAuthorityRepository = routingAuthorityRepository;
            _unitWork = unitWork;
            _userRoleAuthorityRepository = userRoleAuthorityRepository;
            _mapper = mapper;
        }

        /// <summary>
        /// 新增角色权限
        /// </summary>
        /// <param name="model"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task AddAsync(AddRoleModel model)
        {
            if (string.IsNullOrEmpty(model.Code)) throw new InvalidOperationException("角色Code不能为空");
            if (string.IsNullOrWhiteSpace(model.Name)) throw new InvalidOperationException("角色名称不能为空");
            if (await _roleAuthorityRepository.CountAsync(m => (m.Name == model.Name || m.Code == model.Code)) > 0) throw new InvalidOperationException("子系统内的角色名称、编号不允许重复");
            if (model.ActionIDs?.Count > 0 && await _actionAuthorityRepository.CountAsync(m => model.ActionIDs.Contains(m.ID)) != model.ActionIDs.Count)
            {
                throw new InvalidOperationException("选择的功能有误，请刷新后重试");
            }
            if (model.MenuIDs?.Count > 0 && await _menuAuthorityRepository.CountAsync(m => model.MenuIDs.Contains(m.ID)) != model.MenuIDs.Count)
            {
                throw new InvalidOperationException("选择的功能有误，请刷新后重试");
            }
            if (model.RoutingIDs?.Count > 0 && await _routingAuthorityRepository.CountAsync(m => model.RoutingIDs.Contains(m.ID)) != model.RoutingIDs.Count)
            {
                throw new InvalidOperationException("选择的功能有误，请刷新后重试");
            }
            RoleAuthority dbInfo = new();
            model.CopyProperty(dbInfo);
            dbInfo.ID = Guid.NewGuid();
            _unitWork.Add(dbInfo);
            model.ActionIDs?.ForEach(m =>
            {
                RoleAuthorityAction roleAction = new()
                {
                    RoleAuthorityID = dbInfo.ID,
                    ActionAuthorityID = m,
                };
                _unitWork.Add(roleAction);
            });
            model.MenuIDs?.ForEach(m =>
            {
                RoleAuthorityMenu roleMenu = new()
                {
                    RoleAuthorityID = dbInfo.ID,
                    MenuAuthorityID = m
                };
                _unitWork.Add(roleMenu);
            });
            model.RoutingIDs?.ForEach(m =>
            {
                RoleAuthorityRouting roleRouting = new()
                {
                    RoleAuthorityID = dbInfo.ID,
                    RoutingAuthorityID = m
                };
                _unitWork.Add(roleRouting);
            });
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 修改角色权限
        /// </summary>
        /// <param name="model"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task EditAsync(EditRoleModel model)
        {
            if (string.IsNullOrEmpty(model.Code)) throw new InvalidOperationException("角色Code不能为空");
            if (string.IsNullOrWhiteSpace(model.Name)) throw new InvalidOperationException("角色名称不能为空");
            if (model.ID == Guid.Empty) throw new InvalidOperationException("ID不能为空");
            RoleAuthority dbInfo = await _roleAuthorityRepository.FirstAsync(m => m.ID == model.ID) ?? throw new InvalidOperationException("找不到此角色权限");
            if (model.ActionIDs?.Count > 0 && await _actionAuthorityRepository.CountAsync(m => model.ActionIDs.Contains(m.ID)) != model.ActionIDs.Count)
            {
                throw new InvalidOperationException("选择的功能有误，请刷新后重试");
            }
            if (model.MenuIDs?.Count > 0 && await _menuAuthorityRepository.CountAsync(m => model.MenuIDs.Contains(m.ID)) != model.MenuIDs.Count)
            {
                throw new InvalidOperationException("选择的菜单有误，请刷新后重试");
            }
            if (model.RoutingIDs?.Count > 0 && await _routingAuthorityRepository.CountAsync(m => model.RoutingIDs.Contains(m.ID)) != model.RoutingIDs.Count)
            {
                throw new InvalidOperationException("选择的功能有误，请刷新后重试");
            }
            if (await _roleAuthorityRepository.CountAsync(m => (m.Name == model.Name || m.Code == model.Code) && m.ID != model.ID) > 0) throw new InvalidOperationException("子系统内的角色名称、编号不允许重复");
            var subset = await _roleAuthorityRepository.GetAllSubsetAsync(model.ID);
            if (subset?.Count(m => m.ID == model.ParentID) > 0) throw new InvalidOperationException("设置的父级不能再自己的子集中");
            model.CopyProperty(dbInfo);
            _unitWork.Updata(dbInfo);
            var roleMenu = await _roleAuthorityMenuRepository.FindAsync(m => m.RoleAuthorityID == model.ID, null);
            var roleAction = await _roleAuthorityActionRepository.FindAsync(m => m.RoleAuthorityID == model.ID, null);
            var roleRoting = await _roleAuthorityRoutingRepository.FindAsync(m => m.RoleAuthorityID == model.ID, null);
            roleMenu?.ForEach(m => _unitWork.Delete(m));
            roleAction?.ForEach(m => _unitWork.Delete(m));
            roleRoting?.ForEach(m => _unitWork.Delete(m));
            model.ActionIDs?.ForEach(m =>
            {
                RoleAuthorityAction roleAction = new()
                {
                    RoleAuthorityID = dbInfo.ID,
                    ActionAuthorityID = m,
                };
                _unitWork.Add(roleAction);
            });
            model.MenuIDs?.ForEach(m =>
            {
                RoleAuthorityMenu roleMenu = new()
                {
                    RoleAuthorityID = dbInfo.ID,
                    MenuAuthorityID = m
                };
                _unitWork.Add(roleMenu);
            });
            model.RoutingIDs?.ForEach(m =>
            {
                RoleAuthorityRouting roleRouting = new()
                {
                    RoleAuthorityID = dbInfo.ID,
                    RoutingAuthorityID = m
                };
                _unitWork.Add(roleRouting);
            });
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 删除角色
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task DeleteAsync(Guid id)
        {
            var dbInfo = await _roleAuthorityRepository.FirstAsync(m => m.ID == id) ?? throw new InvalidOperationException("找不到此角色权限");
            if (await _userRoleAuthorityRepository.CountAsync(m => m.RoleAuthorityID == id) > 0) throw new InvalidOperationException("有账号正在使用此角色，无法删除");
            _unitWork.Delete(dbInfo);
            var roleMenu = await _roleAuthorityMenuRepository.FindAsync(m => m.RoleAuthorityID == id, null);
            var roleAction = await _roleAuthorityActionRepository.FindAsync(m => m.RoleAuthorityID == id, null);
            var roleRoting = await _roleAuthorityRoutingRepository.FindAsync(m => m.RoleAuthorityID == id, null);
            roleMenu?.ForEach(m => _unitWork.Delete(m));
            roleAction?.ForEach(m => _unitWork.Delete(m));
            roleRoting?.ForEach(m => _unitWork.Delete(m));
            await _unitWork.CommitAsync();
        }

        /// <summary>
        /// 获取
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<List<RoleAuthorityDTO>> GetAsync(List<Guid> ids)
        {
            List<RoleView> dbInfo = await _roleAuthorityRepository.FindRoleView(m => ids.Contains(m.ID));
            var result = _mapper.Map<List<RoleAuthorityDTO>>(dbInfo);
            return result;
        }

        /// <summary>
        /// 获取一级
        /// </summary>
        /// <param name="parentId"></param>
        /// <returns></returns>
        public async Task<List<RoleAuthorityNextLevelListDTO>> GetOneLevelAsync(Guid? parentId)
        {
            List<RoleAuthority> dbInfo = await _roleAuthorityRepository.FindAsync(m => m.ParentID == parentId, m => m.Name, OrderByEnum.Asc);
            var Ids = dbInfo.Select(m => (Guid?)m.ID).ToList();
            var next = await _roleAuthorityRepository.FindAsync(m => Ids.Contains(m.ParentID), m => m.Name, OrderByEnum.Asc);
            var result = _mapper.Map<List<RoleAuthorityNextLevelListDTO>>(dbInfo);
            foreach (var item in result)
            {
                item.ChildrenCount = next.Count(m=>m.ParentID == item.ID);
            }
            return result;
        }

        /// <summary>
        /// 获取树
        /// </summary>
        /// <returns></returns>
        public async Task<List<RoleTreeDTO>> GetTreeAsync()
        {
            List<RoleAuthority> dbInfo = await _roleAuthorityRepository.FindAsync(m => true, m => m.Name, OrderByEnum.Asc);
            var result = TreeConvert.EntityToTreeList<RoleTreeDTO, RoleAuthority>(dbInfo);
            return result;
        }
    }

}